"""
Prometheus监控服务
提供应用性能监控功能
"""

import time
from typing import Optional
from prometheus_client import Counter, Histogram, Gauge, generate_latest, CONTENT_TYPE_LATEST
from prometheus_async import aio
from prometheus_fastapi_instrumentator import Instrumentator
from fastapi import FastAPI
from src.utils.logging import get_logger

logger = get_logger(__name__)

# 定义监控指标
REQUEST_COUNT = Counter(
    "http_requests_total",
    "Total HTTP requests",
    ["method", "endpoint", "status_code"]
)

REQUEST_DURATION = Histogram(
    "http_request_duration_seconds",
    "HTTP request duration in seconds",
    ["method", "endpoint"]
)

ACTIVE_REQUESTS = Gauge(
    "http_active_requests",
    "Number of active HTTP requests"
)

# 业务特定指标
TICKET_CREATED = Counter(
    "tickets_created_total",
    "Total tickets created",
    ["priority", "status"]
)

TICKET_PROCESSING_TIME = Histogram(
    "ticket_processing_seconds",
    "Ticket processing time in seconds",
    ["priority"]
)

USER_REGISTRATIONS = Counter(
    "user_registrations_total",
    "Total user registrations"
)

USER_LOGINS = Counter(
    "user_logins_total",
    "Total user logins",
    ["status"]
)

GROUP_CREATED = Counter(
    "groups_created_total",
    "Total groups created"
)

GROUP_MEMBERS = Gauge(
    "group_members_count",
    "Number of members in groups",
    ["group_id"]
)

# 研究服务指标
RESEARCH_REQUESTS = Counter(
    "research_requests_total",
    "Total research requests",
    ["status", "workflow_type"]
)

RESEARCH_DURATION = Histogram(
    "research_duration_seconds",
    "Research request duration in seconds",
    ["workflow_type"]
)

RESEARCH_SUCCESS_RATE = Gauge(
    "research_success_rate",
    "Research success rate percentage"
)

# 数据库性能指标
DB_QUERY_DURATION = Histogram(
    "db_query_duration_seconds",
    "Database query duration in seconds",
    ["query_type"]
)

DB_CONNECTIONS = Gauge(
    "db_connections_total",
    "Total database connections"
)

DB_CONNECTION_POOL = Gauge(
    "db_connection_pool_size",
    "Database connection pool size"
)

# 缓存性能指标
CACHE_HITS = Counter(
    "cache_hits_total",
    "Total cache hits"
)

CACHE_MISSES = Counter(
    "cache_misses_total",
    "Total cache misses"
)

CACHE_SIZE = Gauge(
    "cache_size_bytes",
    "Cache size in bytes"
)

# 外部服务指标
EXTERNAL_API_CALLS = Counter(
    "external_api_calls_total",
    "Total external API calls",
    ["service", "status", "endpoint"]
)

EXTERNAL_API_DURATION = Histogram(
    "external_api_duration_seconds",
    "External API call duration in seconds",
    ["service", "endpoint"]
)

EXTERNAL_API_ERRORS = Counter(
    "external_api_errors_total",
    "Total external API errors",
    ["service", "error_type", "endpoint"]
)

EXTERNAL_API_TIMEOUTS = Counter(
    "external_api_timeouts_total",
    "Total external API timeouts",
    ["service", "endpoint"]
)

# 飞书服务特定指标
FEISHU_API_CALLS = Counter(
    "feishu_api_calls_total",
    "Total Feishu API calls",
    ["method", "status", "endpoint"]
)

FEISHU_API_DURATION = Histogram(
    "feishu_api_duration_seconds",
    "Feishu API call duration in seconds",
    ["method", "endpoint"]
)

# 知识图谱服务指标
KNOWLEDGE_GRAPH_QUERIES = Counter(
    "knowledge_graph_queries_total",
    "Total knowledge graph queries",
    ["query_type", "status"]
)

KNOWLEDGE_GRAPH_QUERY_DURATION = Histogram(
    "knowledge_graph_query_duration_seconds",
    "Knowledge graph query duration in seconds",
    ["query_type"]
)

KNOWLEDGE_GRAPH_CACHE_HITS = Counter(
    "knowledge_graph_cache_hits_total",
    "Total knowledge graph cache hits",
    ["query_type"]
)

# MCP服务器指标
MCP_SERVER_REQUESTS = Counter(
    "mcp_server_requests_total",
    "Total MCP server requests",
    ["server_name", "method", "status"]
)

MCP_SERVER_DURATION = Histogram(
    "mcp_server_duration_seconds",
    "MCP server request duration in seconds",
    ["server_name", "method"]
)

MCP_SERVER_CONNECTIONS = Gauge(
    "mcp_server_connections_total",
    "Total MCP server connections",
    ["server_name"]
)

# MCP调用链追踪指标
MCP_CALL_TRACE = Counter(
    "mcp_call_traces_total",
    "MCP call traces with full context",
    ["server_name", "method", "status", "caller", "workflow"]
)

MCP_CALL_LATENCY = Histogram(
    "mcp_call_latency_seconds",
    "MCP call latency with full context",
    ["server_name", "method", "caller", "workflow"]
)

# MCP插件使用统计指标
MCP_PLUGIN_USAGE = Counter(
    "mcp_plugin_usage_total",
    "MCP plugin usage statistics",
    ["plugin_name", "server_name", "tool_name", "user_id"]
)

MCP_PLUGIN_ERRORS = Counter(
    "mcp_plugin_errors_total",
    "MCP plugin error statistics",
    ["plugin_name", "server_name", "tool_name", "error_type"]
)

MCP_PLUGIN_RESPONSE_TIME = Histogram(
    "mcp_plugin_response_time_seconds",
    "MCP plugin response time statistics",
    ["plugin_name", "server_name", "tool_name"]
)

# MCP反馈相关指标
MCP_FEEDBACK = Counter(
    'mcp_feedback_total',
    'MCP服务反馈总数',
    ['server_name', 'feedback_type']
)

MCP_FEEDBACK_PROCESSED = Counter(
    'mcp_feedback_processed_total',
    'MCP服务已处理反馈总数',
    ['server_name', 'action_taken']
)

# 错误和异常指标
ERRORS_BY_TYPE = Counter(
    "errors_by_type_total",
    "Total errors by type",
    ["error_type", "endpoint"]
)

RATE_LIMIT_HITS = Counter(
    "rate_limit_hits_total",
    "Total rate limit hits",
    ["client_type"]
)

# 系统资源指标
MEMORY_USAGE = Gauge(
    "memory_usage_bytes",
    "Memory usage in bytes"
)

CPU_USAGE = Gauge(
    "cpu_usage_percent",
    "CPU usage percentage"
)

# 自定义指标注册表
CUSTOM_METRICS = {}

class MonitoringService:
    """监控服务类"""
    
    def __init__(self):
        self.instrumentator = None
        self.metrics_enabled = True
        logger.info("监控服务初始化完成")
    
    def setup_instrumentation(self, app: FastAPI):
        """
        设置FastAPI应用的监控仪器
        
        Args:
            app: FastAPI应用实例
        """
        try:
            from src.config import settings
            
            # 检查是否启用监控
            if not settings.ENABLE_METRICS:
                self.metrics_enabled = False
                logger.info("监控功能已禁用")
                return
            
            # 初始化Instrumentator
            self.instrumentator = Instrumentator(
                should_group_status_codes=False,
                should_ignore_untemplated=True,
                should_respect_env_var=True,
                env_var_name="ENABLE_METRICS",
                should_instrument_requests_inprogress=True,
            )
            
            # 添加默认指标
            self.instrumentator.instrument(app).expose(app)
            logger.info("Prometheus监控仪器设置完成")
        except Exception as e:
            logger.error(f"设置监控仪器失败: {e}")
    
    async def get_metrics(self):
        """
        获取Prometheus指标数据
        
        Returns:
            指标数据和内容类型
        """
        try:
            if not self.metrics_enabled:
                return None, None
                
            metrics_data = generate_latest()
            return metrics_data, CONTENT_TYPE_LATEST
        except Exception as e:
            logger.error(f"获取监控指标失败: {e}")
            return None, None
    
    def record_ticket_created(self, priority: str, status: str):
        """记录工单创建指标"""
        if self.metrics_enabled:
            TICKET_CREATED.labels(priority=priority, status=status).inc()
    
    def record_ticket_processing_time(self, priority: str, duration: float):
        """记录工单处理时间指标"""
        if self.metrics_enabled:
            TICKET_PROCESSING_TIME.labels(priority=priority).observe(duration)
    
    def record_user_registration(self):
        """记录用户注册指标"""
        if self.metrics_enabled:
            USER_REGISTRATIONS.inc()
    
    def record_user_login(self, status: str = "success"):
        """记录用户登录指标"""
        if self.metrics_enabled:
            USER_LOGINS.labels(status=status).inc()
    
    def record_group_created(self):
        """记录群组创建指标"""
        if self.metrics_enabled:
            GROUP_CREATED.inc()
    
    def update_group_members(self, group_id: str, count: int):
        """更新群组成员数量指标"""
        if self.metrics_enabled:
            GROUP_MEMBERS.labels(group_id=group_id).set(count)
    
    def record_research_request(self, status: str, workflow_type: str):
        """记录研究请求指标"""
        if self.metrics_enabled:
            RESEARCH_REQUESTS.labels(status=status, workflow_type=workflow_type).inc()
    
    def record_db_query(self, query_type: str, duration: float):
        """记录数据库查询指标"""
        if self.metrics_enabled:
            DB_QUERY_DURATION.labels(query_type=query_type).observe(duration)
    
    def update_db_connections(self, count: int):
        """更新数据库连接数指标"""
        if self.metrics_enabled:
            DB_CONNECTIONS.set(count)
    
    def update_db_pool_size(self, size: int):
        """更新数据库连接池大小指标"""
        if self.metrics_enabled:
            DB_CONNECTION_POOL.set(size)
    
    def record_cache_hit(self):
        """记录缓存命中指标"""
        if self.metrics_enabled:
            CACHE_HITS.inc()
    
    def record_cache_miss(self):
        """记录缓存未命中指标"""
        if self.metrics_enabled:
            CACHE_MISSES.inc()
    
    def update_cache_size(self, size: int):
        """更新缓存大小指标"""
        if self.metrics_enabled:
            CACHE_SIZE.set(size)
    
    def record_external_api_call(self, service: str, status: str, endpoint: str = "", duration: float = 0.0):
        """记录外部API调用指标"""
        if self.metrics_enabled:
            EXTERNAL_API_CALLS.labels(service=service, status=status, endpoint=endpoint).inc()
            if duration > 0:
                EXTERNAL_API_DURATION.labels(service=service, endpoint=endpoint).observe(duration)
    
    def record_external_api_error(self, service: str, error_type: str, endpoint: str = ""):
        """记录外部API错误指标"""
        if self.metrics_enabled:
            EXTERNAL_API_ERRORS.labels(service=service, error_type=error_type, endpoint=endpoint).inc()
    
    def record_external_api_timeout(self, service: str, endpoint: str = ""):
        """记录外部API超时指标"""
        if self.metrics_enabled:
            EXTERNAL_API_TIMEOUTS.labels(service=service, endpoint=endpoint).inc()
    
    def record_feishu_api_call(self, method: str, status: str, endpoint: str, duration: float = 0.0):
        """记录飞书API调用指标"""
        if self.metrics_enabled:
            FEISHU_API_CALLS.labels(method=method, status=status, endpoint=endpoint).inc()
            if duration > 0:
                FEISHU_API_DURATION.labels(method=method, endpoint=endpoint).observe(duration)
    
    def record_knowledge_graph_query(self, query_type: str, status: str, duration: float = 0.0):
        """记录知识图谱查询指标"""
        if self.metrics_enabled:
            KNOWLEDGE_GRAPH_QUERIES.labels(query_type=query_type, status=status).inc()
            if duration > 0:
                KNOWLEDGE_GRAPH_QUERY_DURATION.labels(query_type=query_type).observe(duration)
    
    def record_knowledge_graph_cache_hit(self, query_type: str):
        """记录知识图谱缓存命中指标"""
        if self.metrics_enabled:
            KNOWLEDGE_GRAPH_CACHE_HITS.labels(query_type=query_type).inc()
    
    def record_mcp_server_request(self, server_name: str, method: str, status: str, duration: float = 0.0):
        """记录MCP服务器请求指标"""
        if self.metrics_enabled:
            MCP_SERVER_REQUESTS.labels(server_name=server_name, method=method, status=status).inc()
            if duration > 0:
                MCP_SERVER_DURATION.labels(server_name=server_name, method=method).observe(duration)
    
    def record_mcp_server_connection(self, server_name: str, count: int):
        """记录MCP服务器连接数"""
        if self.metrics_enabled:
            MCP_SERVER_CONNECTIONS.labels(server_name=server_name).set(count)
    
    def record_mcp_call_trace(self, server_name: str, method: str, status: str, 
                              caller: str = "unknown", workflow: str = "unknown"):
        """记录MCP调用链追踪指标"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_CALL_TRACING:
                MCP_CALL_TRACE.labels(
                    server_name=server_name, 
                    method=method, 
                    status=status,
                    caller=caller,
                    workflow=workflow
                ).inc()
    
    def record_mcp_call_latency(self, server_name: str, method: str, duration: float,
                                caller: str = "unknown", workflow: str = "unknown"):
        """记录MCP调用延迟指标"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_CALL_TRACING:
                MCP_CALL_LATENCY.labels(
                    server_name=server_name,
                    method=method,
                    caller=caller,
                    workflow=workflow
                ).observe(duration)
    
    def record_mcp_plugin_usage(self, plugin_name: str, server_name: str, 
                                tool_name: str, user_id: str = "unknown"):
        """记录MCP插件使用统计"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_PLUGIN_ANALYTICS:
                MCP_PLUGIN_USAGE.labels(
                    plugin_name=plugin_name,
                    server_name=server_name,
                    tool_name=tool_name,
                    user_id=user_id
                ).inc()
    
    def record_mcp_plugin_error(self, plugin_name: str, server_name: str, 
                                tool_name: str, error_type: str):
        """记录MCP插件错误统计"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_PLUGIN_ANALYTICS:
                MCP_PLUGIN_ERRORS.labels(
                    plugin_name=plugin_name,
                    server_name=server_name,
                    tool_name=tool_name,
                    error_type=error_type
                ).inc()
    
    def record_mcp_plugin_response_time(self, plugin_name: str, server_name: str, 
                                        tool_name: str, duration: float):
        """记录MCP插件响应时间统计"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_PLUGIN_ANALYTICS:
                MCP_PLUGIN_RESPONSE_TIME.labels(
                    plugin_name=plugin_name,
                    server_name=server_name,
                    tool_name=tool_name
                ).observe(duration)
    
    def record_mcp_feedback(self, server_name: str, feedback_type: str):
        """记录MCP反馈统计"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_PLUGIN_ANALYTICS:
                MCP_FEEDBACK.labels(
                    server_name=server_name,
                    feedback_type=feedback_type
                ).inc()

    def record_mcp_feedback_processed(self, server_name: str, action_taken: str):
        """记录MCP已处理反馈统计"""
        if self.metrics_enabled:
            from src.config import settings
            if settings.MONITORING_ENABLE_MCP_PLUGIN_ANALYTICS:
                MCP_FEEDBACK_PROCESSED.labels(
                    server_name=server_name,
                    action_taken=action_taken
                ).inc()

    def record_error(self, error_type: str, endpoint: str):
        """记录错误指标"""
        if self.metrics_enabled:
            ERRORS_BY_TYPE.labels(error_type=error_type, endpoint=endpoint).inc()
    
    def record_rate_limit_hit(self, client_type: str):
        """记录速率限制命中指标"""
        if self.metrics_enabled:
            RATE_LIMIT_HITS.labels(client_type=client_type).inc()
    
    def update_system_metrics(self, memory_usage: int, cpu_usage: float):
        """更新系统资源指标"""
        if self.metrics_enabled:
            MEMORY_USAGE.set(memory_usage)
            CPU_USAGE.set(cpu_usage)
    
    def register_custom_metric(self, name: str, metric_type: str, description: str, labels: Optional[list] = None):
        """注册自定义指标"""
        if not self.metrics_enabled:
            return None
            
        if name in CUSTOM_METRICS:
            return CUSTOM_METRICS[name]
        
        # 处理标签参数，确保是列表类型
        label_list = []
        if labels is not None:
            if isinstance(labels, list):
                label_list = labels
            elif isinstance(labels, str):
                label_list = [labels]
        
        if metric_type.lower() == "counter":
            metric = Counter(name, description, label_list)
        elif metric_type.lower() == "gauge":
            metric = Gauge(name, description, label_list)
        elif metric_type.lower() == "histogram":
            metric = Histogram(name, description, label_list)
        else:
            raise ValueError(f"不支持的指标类型: {metric_type}")
        
        CUSTOM_METRICS[name] = metric
        return metric
    
    def register_custom_metric_with_config(self, config: dict):
        """通过配置字典注册自定义指标"""
        required_fields = ["name", "metric_type", "description"]
        for field in required_fields:
            if field not in config:
                raise ValueError(f"缺少必要字段: {field}")
        
        return self.register_custom_metric(
            name=config["name"],
            metric_type=config["metric_type"],
            description=config["description"],
            labels=config.get("labels", [])
        )
    
    def bulk_register_metrics(self, metrics_config: list):
        """批量注册多个自定义指标"""
        results = {}
        for config in metrics_config:
            try:
                metric = self.register_custom_metric_with_config(config)
                results[config["name"]] = metric
            except Exception as e:
                results[config["name"]] = f"注册失败: {str(e)}"
        return results
    
    def list_custom_metrics(self):
        """列出所有已注册的自定义指标"""
        return list(CUSTOM_METRICS.keys())
    
    def remove_custom_metric(self, name: str):
        """移除自定义指标"""
        if name in CUSTOM_METRICS:
            del CUSTOM_METRICS[name]
            return True
        return False
    
    def get_custom_metric(self, name: str):
        """获取自定义指标"""
        return CUSTOM_METRICS.get(name)

# 全局监控服务实例
monitoring_service = MonitoringService()

def instrument_research_function(func):
    """
    研究函数装饰器，用于监控研究请求
    
    Args:
        func: 被装饰的函数
    """
    async def wrapper(*args, **kwargs):
        start_time = time.time()
        try:
            result = await func(*args, **kwargs)
            RESEARCH_REQUESTS.labels(status="success").inc()
            # 记录研究请求持续时间
            duration = time.time() - start_time
            RESEARCH_DURATION.labels(workflow_type="unknown").observe(duration)
            return result
        except Exception as e:
            RESEARCH_REQUESTS.labels(status="error").inc()
            # 记录研究请求持续时间（即使出错也记录）
            duration = time.time() - start_time
            RESEARCH_DURATION.labels(workflow_type="unknown").observe(duration)
            raise e
    
    return wrapper
